home *** CD-ROM | disk | FTP | other *** search
/ Game.EXE 2001 January / Game.EXE_01_2001.iso / demos / Blade of Darkness / data1.cab / Program_Executable_Files / Lib / PythonLib / mailbox.py < prev    next >
Encoding:
Python Source  |  2000-11-16  |  4.9 KB  |  230 lines

  1. #! /usr/bin/env python
  2.  
  3. """Classes to handle Unix style, MMDF style, and MH style mailboxes."""
  4.  
  5.  
  6. import rfc822
  7. import os
  8.  
  9. class _Mailbox:
  10.  
  11.     def __init__(self, fp):
  12.         self.fp = fp
  13.         self.seekp = 0
  14.  
  15.     def seek(self, pos, whence=0):
  16.         if whence==1:        # Relative to current position
  17.             self.pos = self.pos + pos
  18.         if whence==2:        # Relative to file's end
  19.             self.pos = self.stop + pos
  20.         else:            # Default - absolute position
  21.             self.pos = self.start + pos
  22.  
  23.     def next(self):
  24.         while 1:
  25.             self.fp.seek(self.seekp)
  26.             try:
  27.                 self._search_start()
  28.             except EOFError:
  29.                 self.seekp = self.fp.tell()
  30.                 return None
  31.             start = self.fp.tell()
  32.             self._search_end()
  33.             self.seekp = stop = self.fp.tell()
  34.             if start <> stop:
  35.                 break
  36.         return rfc822.Message(_Subfile(self.fp, start, stop))
  37.  
  38. class _Subfile:
  39.  
  40.     def __init__(self, fp, start, stop):
  41.         self.fp = fp
  42.         self.start = start
  43.         self.stop = stop
  44.         self.pos = self.start
  45.  
  46.     def read(self, length = None):
  47.         if self.pos >= self.stop:
  48.             return ''
  49.         if length is None:
  50.             length = self.stop - self.pos
  51.         self.fp.seek(self.pos)
  52.         self.pos = self.pos + length
  53.         return self.fp.read(length)
  54.  
  55.     def readline(self, length = None):
  56.         if self.pos >= self.stop:
  57.             return ''
  58.         if length is None:
  59.             length = self.stop - self.pos
  60.         self.fp.seek(self.pos)
  61.         data = self.fp.readline(length)
  62.         if len(data) < length:
  63.             length = len(data)
  64.         self.pos = self.pos + length
  65.         return data
  66.  
  67.     def tell(self):
  68.         return self.pos - self.start
  69.  
  70.     def seek(self, pos, whence=0):
  71.         if whence == 0:
  72.             self.pos = self.start + pos
  73.         elif whence == 1:
  74.             self.pos = self.pos + pos
  75.         elif whence == 2:
  76.             self.pos = self.stop + pos
  77.  
  78.     def close(self):
  79.         pass
  80.  
  81. class UnixMailbox(_Mailbox):
  82.  
  83.     def _search_start(self):
  84.         while 1:
  85.             line = self.fp.readline()
  86.             if not line:
  87.                 raise EOFError
  88.             if line[:5] == 'From ' and self._isrealfromline(line):
  89.                 return
  90.  
  91.     def _search_end(self):
  92.         while 1:
  93.             pos = self.fp.tell()
  94.             line = self.fp.readline()
  95.             if not line:
  96.                 return
  97.             if line[:5] == 'From ' and self._isrealfromline(line):
  98.                 self.fp.seek(pos)
  99.                 return
  100.  
  101.     # An overridable mechanism to test for From-line-ness.
  102.     # You can either specify a different regular expression
  103.     # or define a whole new _isrealfromline() method.
  104.     # Note that this only gets called for lines starting with
  105.     # the 5 characters "From ".
  106.  
  107.     _fromlinepattern = r"From \s*[^\s]+\s+\w\w\w\s+\w\w\w\s+\d?\d\s+" \
  108.                r"\d?\d:\d\d:\d\d(\s+[^\s]+)?\s+\d\d\d\d\s*$"
  109.     _regexp = None
  110.  
  111.     def _isrealfromline(self, line):
  112.         if not self._regexp:
  113.             import re
  114.             self._regexp = re.compile(self._fromlinepattern)
  115.         return self._regexp.match(line)
  116.  
  117. class MmdfMailbox(_Mailbox):
  118.  
  119.     def _search_start(self):
  120.         while 1:
  121.             line = self.fp.readline()
  122.             if not line:
  123.                 raise EOFError
  124.             if line[:5] == '\001\001\001\001\n':
  125.                 return
  126.  
  127.     def _search_end(self):
  128.         while 1:
  129.             pos = self.fp.tell()
  130.             line = self.fp.readline()
  131.             if not line:
  132.                 return
  133.             if line == '\001\001\001\001\n':
  134.                 self.fp.seek(pos)
  135.                 return
  136.  
  137. class MHMailbox:
  138.  
  139.     def __init__(self, dirname):
  140.         import re
  141.         pat = re.compile('^[0-9][0-9]*$')
  142.         self.dirname = dirname
  143.         files = os.listdir(self.dirname)
  144.         self.boxes = []
  145.         for f in files:
  146.             if pat.match(f):
  147.                 self.boxes.append(f)
  148.  
  149.     def next(self):
  150.         if not self.boxes:
  151.             return None
  152.         fn = self.boxes[0]
  153.         del self.boxes[0]
  154.         fp = open(os.path.join(self.dirname, fn))
  155.         return rfc822.Message(fp)
  156.         
  157.     
  158. class BabylMailbox(_Mailbox):
  159.  
  160.     def _search_start(self):
  161.         while 1:
  162.             line = self.fp.readline()
  163.             if not line:
  164.                 raise EOFError
  165.             if line == '*** EOOH ***\n':
  166.                 return
  167.  
  168.     def _search_end(self):
  169.         while 1:
  170.             pos = self.fp.tell()
  171.             line = self.fp.readline()
  172.             if not line:
  173.                 return
  174.             if line == '\037\014\n':
  175.                 self.fp.seek(pos)
  176.                 return
  177.  
  178.  
  179. def _test():
  180.     import time
  181.     import sys
  182.     import string
  183.     import os
  184.  
  185.     args = sys.argv[1:]
  186.     if not args:
  187.         for key in 'MAIL', 'LOGNAME', 'USER':
  188.             if os.environ.has_key(key):
  189.                 mbox = os.environ[key]
  190.                 break
  191.         else:
  192.             print "$MAIL, $LOGNAME nor $USER set -- who are you?"
  193.             return
  194.     else:
  195.         mbox = args[0]
  196.     if mbox[:1] == '+':
  197.         mbox = os.environ['HOME'] + '/Mail/' + mbox[1:]
  198.     elif not '/' in mbox:
  199.         mbox = '/usr/mail/' + mbox
  200.     if os.path.isdir(mbox):
  201.         mb = MHMailbox(mbox)
  202.     else:
  203.         fp = open(mbox, 'r')
  204.         mb = UnixMailbox(fp)
  205.     
  206.     msgs = []
  207.     while 1:
  208.         msg = mb.next()
  209.         if msg is None:
  210.             break
  211.         msgs.append(msg)
  212.         msg.fp = None
  213.     if len(args) > 1:
  214.         num = string.atoi(args[1])
  215.         print 'Message %d body:'%num
  216.         msg = msgs[num-1]
  217.         msg.rewindbody()
  218.         sys.stdout.write(msg.fp.read())
  219.     else:
  220.         print 'Mailbox',mbox,'has',len(msgs),'messages:'
  221.         for msg in msgs:
  222.             f = msg.getheader('from') or ""
  223.             s = msg.getheader('subject') or ""
  224.             d = msg.getheader('date') or ""
  225.             print '%20.20s   %18.18s   %-30.30s'%(f, d[5:], s)
  226.  
  227.  
  228. if __name__ == '__main__':
  229.     _test()
  230.